//Dynamic Genetic Array Example.
// By Ben  22:15 28/09/2018

#include <iostream>
using namespace std;

//Default array size
#define MIN_SIZE 10;
//This is used when resizing.
#define BY_TWO 2;

template<class T>
class Array{
	size_t n_length;
	size_t n_size;
	T *m_data;

public:
	Array<T>::Array(){
		//Default size for the array
		n_length = MIN_SIZE;
		//Set array size to zero
		n_size = 0;
		//Resize the array the size of the default size.
		m_data = (T*)malloc(n_length*sizeof(*m_data));
	}

	Array<T>::~Array(){
		//Clear up memory after we have finished.
		free(m_data);
	}

	void Array<T>::Push(T Item){
		//If the array size if more than array Length
		if (Size() >= Length())
		{
			//Resize the array to fit the new data been assigned.
			Resize();
		}
		else{
			//Set array element with data from Item
			*(m_data + n_size++) = Item;
		}
	}

	T Array<T>::Get(size_t index){
		//Return array item at index position.
		return *(m_data + index);
	}

	T Array<T>::Pop(){
		//Pop off and remove an item from the array.
		return *(m_data + --n_size);
	}

	void Array<T>::Resize(){
		size_t m_size = Length() * BY_TWO;
		//Resize the array and keep the data
		T *tmp = (T*)realloc(m_data, m_size * sizeof(*m_data));
		//Set array to new data
		m_data = tmp;
		//Set arrays new length
		n_length = m_size;
	}

	size_t Size(){
		//Return the size of the array
		return n_size;
	}

	size_t Length(){
		//Return the length
		return n_length;
	}

	bool IsEmpty(){
		//Tells us if we cannot pop any more items of the array.
		return n_size == 0;
	}
};

int main(){
	Array<int>arr;
	//Push 20 items onto the array
	for (int i = 0;i  <= 20; i++){
		arr.Push(i);
	}

	//Print out the 20 items on the array.
	for (int i = 0; i < arr.Size(); i++){
		std::cout << arr.Get(i) << endl;
	}

	system("pause");
	return 0;
}